package server

import (
    "io/ioutil"
    "log"
    "net/http"
    "net/http/httptest"
    "os"
    "strings"
    "testing"
)

var tests = []struct {
    Code int
    Msg  string
    Data interface{}
}{
    {-1, "failure", ""},
    {0, "success", ""},
}

func TestHttpErrorWrapper(t *testing.T) {
    for _, tt := range tests {
        response := httptest.NewRecorder()
        //request := httptest.NewRequest(http.MethodGet, "/", nil)
        VerifyResponse(response.Result(), tt.Code, tt.Msg, t)
    }
}

func TestHttpErrorWrapperInServer(t *testing.T) {
    //for _, tt := range tests {
    //    server := httptest.NewServer()
    //}
}

func ErrorPanic(write http.ResponseWriter, request *http.Request) error {
    panic("error")
}

func VerifyResponse(response *http.Response, expectedCode int, expectedMsg string, t *testing.T) {
    // 读取响应内容
    b, _ := ioutil.ReadAll(response.Body)
    // 去掉空格
    body := strings.Trim(string(b), "\n")
    // 校验
    if response.StatusCode != expectedCode || body != expectedMsg {
        t.Errorf("expect (%d, %s); got (%d, %s);",
            expectedCode, expectedMsg, response.StatusCode, body)
    }
}

// 错误处理器类型，可以处理的HTTP路由处理器就是此类型，参数和返回值一致
type HttpErrorHandler func(writer http.ResponseWriter, request *http.Request) error

// HTTP错误统一处理
// 接收错误处理器类型，返回值是一个函数，是真正处理HTTP的函数
func HttpErrorWrapper(handler HttpErrorHandler) func(http.ResponseWriter, *http.Request) {
    return func(writer http.ResponseWriter, request *http.Request) {
        // 处理panic抛出的错误
        defer func() {
            if r := recover(); r != nil {
                log.Printf("Panic: %v", r)
                // 响应错误消息
                http.Error(writer, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
            }
        }()
        // 提取错误，传入响应对象和请求对象，得到一个错误
        // 也就是HttpErrorHandler类型函数的处理结果
        err := handler(writer, request)
        if err != nil {
            // 处理请求遇到了错误
            log.Printf("Error occurred handling request: %s", err.Error())
            // 如果是用户错误
            // 类型转换，将错误转换为用户错误
            //if userError, ok := err.(filestring.UserError); ok {
            //    http.Error(writer, userError.Message(), http.StatusBadRequest)
            //    return
            //}
            // 如果是系统错误
            code := http.StatusOK
            switch {
            case os.IsNotExist(err):
                code = http.StatusNotFound
            case os.IsPermission(err):
                code = http.StatusForbidden
            default:
                code = http.StatusInternalServerError
            }
            http.Error(writer, http.StatusText(code), code)
        }
    }
}
